package com.javasm.mingming.socket;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @author javasm
 * @version 0.1
 * @className PrivateChatSocket
 * @descriptioin:
 * @date 2025/1/21 14:36
 * @since jdk11
 */
@Component
@ServerEndpoint("/private/chat/{fromUid}/{toUid}")
public class PrivateChatSocket {
    //把当前的一对一聊天，当作特殊的房间来看待,房间ID，房间内的session集合
    private static Map<String, Set<Session>> roomMap = new ConcurrentHashMap<>(8);
    //房间内，用户的集合 Map<房间ID，Map<uid，Session>>
    private static Map<String,Map<String,Session>> roomUserMap = new ConcurrentHashMap<>(8);

    //可能 很多人，都给用户发送了离线消息，用全局变量存储，相当于把聊天记录存到了JVM中，有隐患
    //假设，很多人，给同一个用户，发了很多消息
    //Map<收信人UId toUid，Map<发信人Uid fromUid,List<消息内容>>>
    private static Map<String,Map<String, List<String>>> historyMessageMap = new ConcurrentHashMap<>(8);



    @OnOpen
    public void enterRoom(@PathParam("fromUid")String fromUid,
                          @PathParam("toUid")String toUid,
                          Session session){
        //假设 fromUid = 20  toUid = 19 RoomId = "19-20"
        //假设 fromUid = 19  toUid = 20 RoomId = "19-20"
       String roomId = doRoomId(fromUid,toUid);
       //获取 当前房间的 session列表
        Set<Session> set = roomMap.get(roomId);

        Map<String, Session> userMap = roomUserMap.get(roomId);
        if (set == null){
            //之前没有建立聊天，或者说俩人都已经离线过了，这一次是第一次发消息
            set = new CopyOnWriteArraySet<>();
            //session存入set
            set.add(session);
            //session集合存入map
            roomMap.put(roomId,set);
            userMap = new ConcurrentHashMap<>();
            userMap.put(fromUid,session);
            roomUserMap.put(roomId,userMap);
        }else {
            //之前房间里有人
            set.add(session);
            userMap.put(fromUid,session);
        }
        //用户进入房间，读 发给我的离线消息
        Map<String, List<String>> listMap = historyMessageMap.get(fromUid);
        //所有人给我发的消息，都在listMap中
        if (listMap != null){
            //fromUid打开的聊天框，想和toUid聊天
            //获取 对面 toUid这个人 之前给我发的历史消息
            List<String> msgList = listMap.get(toUid);
            if (msgList!=null&&msgList.size()>0){
                msgList.forEach(msg->{
                    try {
                        session.getBasicRemote().sendText(msg);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });
                //历史记录发送完成
                clearMessageList(fromUid,toUid);
                //读取了历史消息，减去已读消息数量
                SystemSocket.readMessage(fromUid,msgList.size());
            }
        }
    }

    private void clearMessageList(String fromUid, String toUid) {
        Map<String, List<String>> listMap = historyMessageMap.get(fromUid);
        if (listMap != null){
            listMap.remove(toUid);
        }

    }

    @OnClose
    public void close(@PathParam("fromUid")String fromUid,
                      @PathParam("toUid")String toUid,
                      Session session){
        //离开房间
        String roomId = doRoomId(fromUid,toUid);
        if (roomMap.containsKey(roomId)){
            roomMap.get(roomId).remove(session);

        }
        if (roomUserMap.containsKey(roomId)){
            roomUserMap.get(roomId).remove(fromUid);
        }
    }
    @OnError
    public void error(Throwable e){
        e.printStackTrace();
    }

    @OnMessage
    public void replyMessage(@PathParam("fromUid")String fromUid,
                             @PathParam("toUid")String toUid,
                             Session session,String message){
        sendMessage(fromUid,toUid,message);
    }

    private void sendMessage(String fromUid, String toUid, String message) {
        String roomId = doRoomId(fromUid,toUid);
        //获取 当前房间中，用户的session集合
        Set<Session> sessions = roomMap.get(roomId);
        try {
            if (sessions != null){
                for (Session s : sessions){
                    s.getBasicRemote().sendText(message);
                }
            }
            //消息 发送完成
            //收消息的人，是否在房间内，toUid用户 是否打开了聊天框，是否进入到聊天界面
            //如果在聊天界面，直接发送内容，如果不在，发离线消息
            Map<String, Session> userSessionMap = roomUserMap.get(roomId);
            //寻找，当前房间里，另一个人的session对象
            Session session = userSessionMap.get(toUid);
            if (session == null){
                //这个人不在房间里
                sendHistoryMessage(fromUid,toUid,message);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void sendHistoryMessage(String fromUid, String toUid, String message) {
        //发离线消息
        //查看之前 是否给这个人发过离线消息
        Map<String, List<String>> fromUserMsgMap = historyMessageMap.get(toUid);
        if (fromUserMsgMap == null){
            //之前 所有人 都没给他发过离线消息
            fromUserMsgMap = new ConcurrentHashMap<>();
        }
        //执行到这里listMap肯定不是null
        //获取 我  给 他 发消息的历史记录
        List<String> msgList = fromUserMsgMap.get(fromUid);
        if (msgList == null){
            //之前没有发过离线消息
            msgList = new ArrayList<>();
        }
        //把新消息 添加到 集合中
        msgList.add(message);
        fromUserMsgMap.put(fromUid,msgList);
        historyMessageMap.put(toUid,fromUserMsgMap);
        //发送系统消息，提示几条未读
        SystemSocket.addUnreadMessage(toUid);

    }

    public String doRoomId(String fromUid, String toUid) {
        return Arrays.stream(new String[]{fromUid, toUid})
                .sorted()
                .reduce((a, b) -> a + "-" + b)
                .orElse("");
    }

}
